package ar.edu.utn.frba.disenio.aterrizar;

import ar.edu.utn.frba.disenio.aterrizar.aerolineas.AdapterLanchita;
import ar.edu.utn.frba.disenio.aterrizar.aerolineas.Aerolinea;
import ar.edu.utn.frba.disenio.aterrizar.aerolineas.Vuelo;
import ar.edu.utn.frba.disenio.aterrizar.busquedas.CriterioBusqueda;
import ar.edu.utn.frba.disenio.aterrizar.compra.ManagerCompras;
import ar.edu.utn.frba.disenio.aterrizar.excepciones.AsientoErroneoException;
import ar.edu.utn.frba.disenio.aterrizar.filtros.Filtro;
import ar.edu.utn.frba.disenio.aterrizar.orden.Orden;
import ar.edu.utn.frba.disenio.aterrizar.orden.PrecioAscendente;
import ar.edu.utn.frba.disenio.aterrizar.orden.PrecioDescendente;
import ar.edu.utn.frba.disenio.aterrizar.orden.TiempoVuelo;
import ar.edu.utn.frba.disenio.aterrizar.reserva.ManagerReserva;
import ar.edu.utn.frba.disenio.aterrizar.reserva.Reserva;
import ar.edu.utn.frba.disenio.aterrizar.reserva.ReservaUsuario;
import ar.edu.utn.frba.disenio.aterrizar.usuario.Usuario;
import ar.edu.utn.frba.disenio.aterrizar.usuario.UsuarioEstandar;
import ar.edu.utn.frba.disenio.aterrizar.usuario.UsuarioNoPaga;
import ar.edu.utn.frba.disenio.aterrizar.usuario.UsuarioVip;

import com.lanchita.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Collection;

public class LanchitaMockTest {

	Usuario usuarioEstandar1 = new UsuarioEstandar("Juan","Perez","123456");
	Usuario usuarioEstandar2 = new UsuarioEstandar("Pedro", "Lopez", "13205412");
	Usuario usuarioVip = new UsuarioVip("Laura","Rodriguez","9877654");
	Usuario usuarioNoPaga = new UsuarioNoPaga("Pepe","Argento","567842");
	
	AerolineaLanchita mockAerolineaLanchita = mock(AerolineaLanchita.class);
	AerolineaLanchita mockitoLanchita = mockAerolineaLanchita.getInstance();
	Aerolinea mockAdapter = new AdapterLanchita(mockitoLanchita);
	ManagerReserva managerReserva = new ManagerReserva();
	ManagerCompras managerCompras = new ManagerCompras();
	
	CriterioBusqueda busqueda = new CriterioBusqueda("EZE","USA","21/12/2012",1);
	
	@Test
	public void testResultadosBusquedaVipSinFiltroSinOrden(){
		usuarioVip.buscarVuelos(mockAdapter, busqueda, null,null);
		for(ArrayList<Vuelo> unaBusqueda : usuarioVip.getBusquedas()){
			assertTrue(unaBusqueda.size()==7);			
		}
	}
	
	@Test
	public void testResultadosBusquedaEstandarSinFiltroSinOrden(){
		usuarioEstandar1.buscarVuelos(mockAdapter, busqueda, null,null);
		for(ArrayList<Vuelo> unaBusqueda : usuarioEstandar1.getBusquedas()){
			assertTrue(unaBusqueda.size()==3);
		}
	}
	
	@Test
	public void testResultadosBusquedaNoPagaSinFiltroSinOrden(){
		usuarioNoPaga.buscarVuelos(mockAdapter, busqueda, null,null);
		for(ArrayList<Vuelo> unaBusqueda : usuarioNoPaga.getBusquedas()){
			assertTrue(unaBusqueda.size()==3);
		}
	}
	
	@Test
	public void testValorDeAsientoVip(){
		double precio = mockAdapter.buscarVueloParticular("01202022220202-3", usuarioVip).valor;
		assertTrue( precio == 183.885);
	}
	
	@Test
	public void testValorDeAsientoEstandar(){
		double precio = mockAdapter.buscarVueloParticular("01202022220202-3", usuarioEstandar1).valor;
		assertTrue( precio == 183.885);
	}
	
	@Test
	public void testValorDeAsientoNoPaga(){
		double precio = mockAdapter.buscarVueloParticular("01202022220202-3", usuarioNoPaga).valor;
		assertTrue(precio == 203.885);
	}
	
	@Test
	public void testAplicandoFiltroUbicacion(){
		Filtro filtro = new Filtro();
		filtro.ubicacion = "Ventana";
		usuarioVip.buscarVuelos(mockAdapter, busqueda, filtro, null);
		for(ArrayList<Vuelo> unaBusqueda : usuarioVip.getBusquedas()){
			assertTrue(unaBusqueda.size()==3);			
		}
	}
	
	@Test
	public void testAplicandoFiltroClases(){
		Collection<String> clases = new ArrayList<String>();
		clases.add("Ejecutivo");
		clases.add("Primera");
		Filtro filtro = new Filtro();
		filtro.addFiltroClase(clases);
		usuarioVip.buscarVuelos(mockAdapter, busqueda, filtro, null);
		for(ArrayList<Vuelo> unaBusqueda : usuarioVip.getBusquedas()){
			assertTrue(unaBusqueda.size()==4);			
		}		
	}
	
	@Test
	public void testAplicandoFiltroPrecio(){
		Filtro filtro = new Filtro();
		filtro.addFiltroPrecio(0, 200);
		usuarioVip.buscarVuelos(mockAdapter, busqueda, filtro, null);
		for(ArrayList<Vuelo> unaBusqueda : usuarioVip.getBusquedas()){
			assertTrue(unaBusqueda.size()==2);			
		}		
	}
	
	@Test
	public void testAplicandoTodosLosFiltros(){
		Collection<String> clases = new ArrayList<String>();
		clases.add("Ejecutivo");
		clases.add("Primera");
		Filtro filtro = new Filtro();
		filtro.addFiltroClase(clases);
		filtro.addFiltroUbicacion("Ventana");
		filtro.addFiltroPrecio(0, 200);
		usuarioVip.buscarVuelos(mockAdapter, busqueda, filtro, null);
		for(ArrayList<Vuelo> unaBusqueda : usuarioVip.getBusquedas()){
			assertTrue(unaBusqueda.size()==1);			
		}	
	}
	
	@Test
	public void testAplicandoOrdenPrecioAscendente(){
		ArrayList<String> expected = new ArrayList<String>();
		ArrayList<String> observed = new ArrayList<String>();
		
		expected.add("01202012315523-8");
		expected.add("01202022220202-3");
		expected.add("01202022220123-3");
		expected.add("01202022256565-3");
		expected.add("01202022220008-3");
		expected.add("01202022323423-5");
		expected.add("01202022220298-2");
							  			
		Orden unOrden = new PrecioAscendente();
		usuarioVip.buscarVuelos(mockAdapter, busqueda, null, unOrden);
	
		for(ArrayList<Vuelo> busqueda : usuarioVip.getBusquedas()){
			for(Vuelo unVuelo : busqueda){
				observed.add(unVuelo.codigo);				
			}
		}
		assertTrue("El orden observado en la busqueda debe ser igual al esperado",observed.equals(expected));
	}
	
	@Test
	public void testAplicandoOrdenPrecioDescendente(){
		ArrayList<String> expected = new ArrayList<String>();
		ArrayList<String> observed = new ArrayList<String>();
				
		expected.add("01202022220298-2");
		expected.add("01202022323423-5");		
		expected.add("01202022220008-3");
		expected.add("01202022256565-3");
		expected.add("01202022220123-3");
		expected.add("01202022220202-3");
		expected.add("01202012315523-8");
		
		Orden unOrden = new PrecioDescendente();
		usuarioVip.buscarVuelos(mockAdapter, busqueda, null, unOrden);
	
		for(ArrayList<Vuelo> busqueda : usuarioVip.getBusquedas()){
			for(Vuelo unVuelo : busqueda){
				observed.add(unVuelo.codigo);				
			}
		}
		assertTrue("El orden observado en la busqueda debe ser igual al esperado",observed.equals(expected));
	}
	
	@Test
	public void testAplicandoOrdenTiempoVuelo(){
		ArrayList<String> expected = new ArrayList<String>();
		ArrayList<String> observed = new ArrayList<String>();
					
		expected.add("01202022220008-3");
		expected.add("01202022256565-3");
		expected.add("01202022323423-5");		
		expected.add("01202022220202-3");
		expected.add("01202022220123-3");
		expected.add("01202012315523-8");
		expected.add("01202022220298-2");
				
		Orden unOrden = new TiempoVuelo();
		usuarioVip.buscarVuelos(mockAdapter, busqueda, null, unOrden);
	
		for(ArrayList<Vuelo> busqueda : usuarioVip.getBusquedas()){
			for(Vuelo unVuelo : busqueda){
				observed.add(unVuelo.codigo);				
			}
		}
		assertTrue("El orden observado en la busqueda debe ser igual al esperado",observed.equals(expected));
	}

	@Test 
	public void testBorrarExpiradosDeUnaReservaDeLanchitaEnClaseManagerReserva(){
		managerReserva.reservar(mockAdapter, usuarioEstandar1, "01202022267867-7");
		managerReserva.reservar(mockAdapter, usuarioEstandar2, "01202022267867-7");
		Reserva unaReserva=managerReserva.buscar(mockAdapter, "01202022267867-7");
		managerReserva.borrarExpirados(mockAdapter, "01202022267867-7");
		ReservaUsuario unaReservaUsuario=unaReserva.reservaUsuarios.get(0);
		String fecha=managerReserva.getFechaActual();
		assertTrue(unaReservaUsuario.getFechaActual().equals(fecha) && unaReservaUsuario.getUsuario().equals(usuarioEstandar2));
	}
	
	@Test
	public void testBorrarSobreReservasDeUnaReservaDeLanchitaEnClaseManagerReserva(){
		usuarioEstandar1.reservar("01202022256565-3", mockAdapter, managerReserva);
		usuarioEstandar2.reservar("01202022256565-3", mockAdapter, managerReserva);
		Reserva unaReserva=managerReserva.buscar(mockAdapter, "01202022256565-3");
		managerReserva.borrarSobreReservas(mockAdapter, "01202022256565-3");
		int tamanioDespuesDeBorrar=unaReserva.reservaUsuarios.size();
		assertTrue(tamanioDespuesDeBorrar==1);
	}
	
	@Test
	public void testReservarAsientoOk(){
		usuarioEstandar1.reservar("01202022323423-5", mockAdapter, managerReserva);
	}
	
	@Test
	public void testSobreReservarOk(){
		usuarioEstandar1.reservar("01202022220298-2", mockAdapter, managerReserva);
		usuarioEstandar2.reservar("01202022220298-2", mockAdapter, managerReserva);
	}
	
	@Test
	public void testCompraAsientoErroneo() {
		usuarioVip.comprarAsiento(mockAdapter, "asdlkajfg5646mvad", managerCompras);
	}
	
	@Test(expected = AsientoErroneoException.class)
	public void testCompraAsientoExitoso() {
		usuarioVip.comprarAsiento(mockAdapter, "01202022220202-3", managerCompras);
		mockAdapter.buscarVueloParticular("01202022220202-3", usuarioVip);
	}
}
